<template>
	<view ref="wrapper" class="wrapper" :style="'height:' + WindowInfo.windowHeight + 'px'">
		<!-- 头部 -->
		<view class="header-box">
			<u-navbar height="120rpx" safeAreaInsetTop placeholder bgColor="#FFFFFF"
				titleStyle="font-size: 16px; font-weight: 500; color: #000000;" class="navbar" @leftClick="backChat">
				<view class="u-center-slot" slot="center">
					<view class="nav-title omit">ChatGPT</view>
					<view class="nav-system" v-if="isThinking">{{ $t("contacts.AIThinking") }}</view>
				</view>
				<view class="u-right-slot" slot="right" @click="clearChatGpt">
					<view class="iconfont icon-shanchuliaotianjilu clear"></view>
				</view>
			</u-navbar>
		</view>

		<!-- 中间聊天内容区域 -->
		<scroll-view class="chat-box" id="chat-box" scroll-y="true" :scroll-into-view="scrollIntoView"
			@scrolltoupper="scrollToUpper">
			<view style="width: 100%; height: 30rpx"></view>
			<view v-for="(item, index) in chatList" :key="item.messageUId" :id="`S-${item.messageUId}`">
				<!-- 我发的信息 -->
				<view v-if="item.type == 'me'">
					<view class="chat-line chat-right" :id="`index${index}`">
						<view class="chat-line__container" style="margin-right: -24rpx">
							<!-- 普通文本信息 -->
							<view class="connect-block-right" v-html="item.content">
							</view>
							<view v-if="index === (chatList.length - 1) && isThinking" class="left-regenerate right-stop" @click="stopAI">{{ $t("contacts.AIStop") }}</view>
						</view>
					</view>
				</view>

				<!-- 对方发的信息 -->
				<view v-else>
					<view class="chat-line" :id="`index${index}`">
						<!-- 头像 -->
						<ChatGPTLogo class="avatar"></ChatGPTLogo>
						<view class="chat-line__container">
							<!-- 普通文本信息 -->
							<view class="connect-block-left" v-highlight v-html="item.markedContent">
							</view>
							<view v-if="index === (chatList.length - 1)" class="left-regenerate" @click="regenerateAI">{{ $t("contacts.AIRegenerate") }}</view>
						</view>
					</view>
				</view>
			</view>
		</scroll-view>

		<!-- 底部操作栏 -->
		<view class="bottom-box" :style="{ position: 'relative', bottom: keyHeight + 'px' }">
			<view class="input-line">
				<input ref="scanTextbox" :placeholder="$t('chat.Message')" class="message-input ml-10 mr-l0"
					placeholder-style="font-size: 26upx;color: #878787;" :confirm-type="$t('chat.send')" :confirm-hold="true"
					@confirm="haddleSendMsg" v-model="messageContent" :adjust-position="false" maxlength="-1" />
				<image class="send-icon" :src="require('@/static/image/chat/send.png')" @touchend.prevent="haddleSendMsg"></image>
			</view>
		</view>
	</view>
</template>

<script>
// 将marked 引入
import { marked } from 'marked';
// 引入代码高亮样式
import "highlight.js/styles/vs.css";
import { mapState } from "vuex";
import { getChatGPT, stopChatFPT } from "@/services/chat.js"
import ChatGPTLogo from "./components/ChatGPTLogo.vue";
import { initChatGPT, clearChatGPTMsg } from '@/utils/util.js'
var appInstance = getApp();
export default {
	name: "GptRoom",
	components: { ChatGPTLogo },
	data() {
		return {
			WindowInfo: {},
			keyHeight: 0,
			messageContent: "",
			chatList: [], // 会话列表
			scrollTop: 0,
			// 底部消息栏显示类型
			scrollIntoView: "",
			backType: null,
			isThinking: false
		};
	},
	computed: {
		...mapState([
			"userId",
			"userInfo",
			"token",
		]),
	},
	watch: {
		chatList: {
			handler(newVal, oldVal) {
				if (newVal) {
					appInstance.globalData.gptChatList = newVal
					let copyTextSuccess = this.$t("contacts.copyTextSuccess")
					let copyText = this.$t('contacts.Copy')
					this.$nextTick(() => {
						let arr = document.getElementsByTagName("pre")
						if (arr && arr.length > 0) {
							// console.log('代码模块数量', arr)
							for (let i = 0; i < arr.length; i++) {
								if (this.isHaveCopyNode(arr[i].childNodes)) {
									continue
								} else {
									let divCopy = document.createElement("div")
									divCopy.innerText = copyText
									divCopy.style.width = "fit-content"
									divCopy.style.padding = "0px 16px"
									divCopy.style.marginLeft = "auto"
									divCopy.style.fontSize = "14px"
									divCopy.style.fontColor = "#CCCCCC"
									divCopy.style.opacity = '0.5'
									divCopy.onclick = function () {
										let text = arr[i].childNodes[0].innerText
										if (navigator.clipboard) {
											navigator.clipboard.writeText(text).then(
												function () {
													uni.showToast({
														title: copyTextSuccess,
														icon: "none",
													});
												},
												function () {
													const div = document.createElement("div")
													div.style.position = "absolute";
													div.style.top = "-1000px";
													div.style.left = 0;
													div.style.opacity = 0;
													div.style.zIndex = -10;
													div.className = "";
													div.innerText = text
													document.body.appendChild(div);
													const range = document.createRange();
													range.selectNode(div);
													const selection = document.getSelection();
													//移除之前选中内容
													if (selection.rangeCount > 0) selection.removeAllRanges();
													selection.addRange(range);
													if (document.execCommand("copy")) {
														document.execCommand("copy");
														uni.showToast({
															title: copyTextSuccess,
															icon: "none",
														});
													}
													selection.removeAllRanges();
													document.body.removeChild(div);
												}
											);
										} else {
											const div = document.createElement("div")
											div.style.position = "absolute";
											div.style.top = "-1000px";
											div.style.left = 0;
											div.style.opacity = 0;
											div.style.zIndex = -10;
											div.className = "";
											div.innerText = text
											document.body.appendChild(div);
											const range = document.createRange();
											range.selectNode(div);
											const selection = document.getSelection();
											//移除之前选中内容
											if (selection.rangeCount > 0) selection.removeAllRanges();
											selection.addRange(range);
											if (document.execCommand("copy")) {
												document.execCommand("copy");
												uni.showToast({
													title: copyTextSuccess,
													icon: "none",
												});
											}
											selection.removeAllRanges();
											document.body.removeChild(div);
										}
									}
									arr[i].appendChild(divCopy)
								}
							}
						}
					})
					// console.log('赋值chatGPT聊天数据', newVal)
				}
			},
		}
	},
	methods: {
		marked,
		// 清空ChatGpt
    clearChatGpt () {
			this.chatList = []
			this.isThinking = false
      clearChatGPTMsg()
    },
		stopAI() {
			this.isThinking = false
			stopChatFPT()
		},
		regenerateAI() {
			if (this.isThinking) {
				return uni.showToast({
					title: this.$t("contacts.AIThinking"),
					icon: "none",
				});
			}
			this.isThinking = true
			this.chatList = this.chatList.slice(0,-1)
			if (this.chatList && this.chatList.length > 0 && this.isThinking) {
				this.toSendGPT(this.chatList[this.chatList.length - 1].content)
			} else {
				this.isThinking = false
			}
		},
		isHaveCopyNode(arr) {
			var copyText = this.$t('contacts.Copy')
			var nodeName = false
			if (arr && arr.length > 0) {
				for (let i = 0; i < arr.length; i++) {
					if (arr[i].localName != 'code' && arr[i].innerText == copyText) {
						nodeName = true
					}
				}
			}
			return nodeName
		},
		backChat() {
			if (this.backType || getCurrentPages().length < 2) {
				uni.switchTab({
					url: "/pages/chat/Chat",
				});
			} else {
				uni.navigateBack();
			}
		},
		haddleSendMsg() {
			if (this.isThinking) {
				return uni.showToast({
					title: this.$t("contacts.AIThinking"),
					icon: "none",
				});
			}
			if (!this.messageContent) {
				return uni.showToast({
					title: this.$t("chat.Empty-messages-cannot-be-sent"),
					icon: "none",
				});
			}
			this.isThinking = true
			this.chatList.push({
				type: 'me',
				content: this.messageContent,
				messageUId: new Date().getTime()
			})
			let msg = this.messageContent
			this.messageContent = ''
			this.scrollToBottom()
			this.toSendGPT(msg)
		},
		async toSendGPT(msg) {
			const resp = await getChatGPT({
				content: msg
			})
			if (resp.result.code == 200) {
				this.chatList.push({
					type: 'chatGPT',
					content: resp.result.rows[0],
					markedContent: this.deleteTheLast(marked(resp.result.rows[0]).replace(/\n/g, '<br />')),
					messageUId: new Date().getTime()
				})
				this.scrollToBottom()
				// console.log('chatGPT回答结果', resp.result.rows[0])
			}
			this.isThinking = false
		},

		deleteTheLast(msg) {
			if(!msg || msg.length < 6) {
				return msg
			}
			if (msg.substring(msg.length - 6) == '<br />') {
				return msg.substring(0, msg.length - 6)
			} else {
				return msg
			}
		},

		getTotalChatList() {
			this.chatList = appInstance.globalData.gptChatList
			if (this.chatList && this.chatList.length > 0) {
				this.scrollToBottom()
			}
		},

		// 滚动到顶部
		async scrollToUpper(e) {

		},
		// 自动滚动到底部位置
		scrollToBottom() {
			const arrLength = this.chatList.length - 1;
			const lastMessId = this.chatList[arrLength]?.messageUId;
			this.scrollIntoView = "";
			setTimeout(() => {
				this.scrollIntoView = `S-${lastMessId}`;
			}, 10);
		},
	},
	onLoad(option) {
		initChatGPT()
		// 获取全局数据
		this.getTotalChatList()
		setTimeout(() => {
			this.WindowInfo = uni.getWindowInfo();
		}, 100);
		this.backType = Number(option.backType || 0);
		uni.onKeyboardHeightChange((res) => {
			// 监听软键盘的高度，页面隐藏后一定要取消监听键盘
			this.keyHeight = res.height;
		});
	},
	onUnload() {
		uni.offKeyboardHeightChange((res) => { });
	},
};
</script>

<style lang="scss" scoped>
.clear {
	font-size: 44upx;
	color: black;
	margin: 0 16upx 0 48upx;
	position: relative;
	z-index: 10;
	color: #4d4d4d;
}

.omit {
	text-overflow: -o-ellipsis-lastline;
	overflow: hidden;
	text-overflow: ellipsis;
	display: -webkit-box;
	-webkit-line-clamp: 1;
	line-clamp: 1;
	-webkit-box-orient: vertical;
	word-wrap: break-word;
	white-space: pre-wrap;
	word-break: break-word;
	font-size: 24rpx;
}

.wrapper {
	width: 100%;
	height: 100vh;
	background: #e9edec;
	display: flex;
	flex-direction: column;

	.header-box {
		.u-center-slot {
			width: 80%;
			margin: 0rpx 10%;

			.nav-title {
				font-size: 32upx;
				font-weight: 500;
				color: #000000;
				line-height: 48upx;
				text-align: center;
			}

			.nav-system {
				margin-top: 6upx;
				margin-left: 12upx;
				font-size: 24upx;
				font-weight: 400;
				color: #878787;
				position: relative;
				text-align: center;
				// line-height: 1em;
			}
		}
	}

	.chat-box {
		width: 100%;
		flex: 1;
		overflow: scroll;
		background: #e9edec;
		box-sizing: border-box;
		padding: 0rpx 30rpx 0;

		.chat-line {
			width: 100%;
			display: flex;
			padding-bottom: 30upx;

			.left-regenerate {
				width: fit-content;
				height: 50upx;
				line-height: 50upx;
				margin-top: 20upx;
				margin-left: 24upx;
				border: 1upx solid #000000;
				padding: 0upx 10upx;
				border-radius: 10upx;
				font-size: 28upx;
				opacity: 0.5;
			}

			.right-stop {
				margin-left: auto !important;
				margin-right: 24upx;
			}

			&.chat-right {
				justify-content: flex-end;
			}

			.avatar {
				flex-shrink: 0;
				width: 80upx;
				height: 80upx;
				border-radius: 50%;
				line-height: 80rpx;
				text-align: center;
				font-size: 30rpx;
				font-weight: 400;
				color: #fff;
			}

			.connect-block-left {
				background: #ffffff;
				border-radius: 0px 20rpx 20rpx 20rpx;
				font-family: HarmonyOS Sans-Regular, HarmonyOS Sans;
				box-sizing: border-box;
				padding: 20upx 30upx;
				margin: 0 104upx 0 24upx;
				font-size: 28upx;
				font-weight: 400;
				color: rgba(0, 0, 0, 0.8);
				line-height: 44upx;
				word-wrap: break-word;
				white-space: pre-wrap;
				word-break: break-word;
				width: fit-content;
				overflow: hidden;
				max-width: 510rpx;

				::v-deep pre {
					width: 100%;
					border-radius: 20rpx;
					padding-bottom: 16rpx;
					background-color: #64748b10;
				}

				::v-deep .hljs {
					width: 100%;
					border-radius: 20rpx;
					padding: 16rpx 32rpx;
					box-sizing: border-box;
					overflow-x: auto;
					background-color: unset;
				}
			}

			.connect-block-right {
				overflow: hidden;
				border-radius: 20rpx 0px 20rpx 20rpx;
				background: #61bdb2;
				box-sizing: border-box;
				padding: 20upx 30upx;
				margin: 0 24upx 0 104upx;
				font-size: 28upx;
				font-weight: 400;
				color: #ffffff;
				line-height: 44upx;
				word-break: break-word; // 强制换行
			}
		}
	}

	.msgs-classic {
		min-width: 430upx;
		text-align: left;
		overflow: hidden;
		display: inline-block;
		padding: 0rpx 20rpx;
		background: #61bdb2;
		color: #ffffff;
		white-space: pre-line;
		word-break: break-word;
		background-blend-mode: multiply;
		box-sizing: border-box;
		border-radius: 20rpx 0rpx 20rpx 20rpx;
		margin: 0 24upx 0 104upx;
		overflow: hidden;
	}

	.bottom-box {
		z-index: 11;
		position: fixed;
		bottom: 0;
		width: 100%;
		background: #ffffff;
		box-shadow: 0 0 10upx 0 rgba(204, 0, 51, 0.1);

		.input-line {
			position: relative;
			box-sizing: border-box;
			padding: 18upx 30upx;
			display: flex;
			align-items: center;

			.send-icon {
				width: 64rpx;
				height: 64rpx;
			}

			.message-input {
				flex: 1;
				height: 76upx;
				background: #f6f6f6;
				border-radius: 38upx;
				font-size: 28upx;
				font-weight: 400;
				color: #000000;
				box-sizing: border-box;
				padding: 0 40upx;
			}

			.margin-left {
				margin-left: 24upx;
			}
		}
	}
}

.ml-10 {
	margin-left: 10rpx;
}

.mr-l0 {
	margin-right: 10rpx;
}

/deep/ .uni-input-input {
	word-break: break-all;
	width: 90%;
}
</style>